//? 使用场景:new
Function.prototype.calll = function (obj,...args) {
    //? globalThis代表当前环境里的this
    !obj && (obj = globalThis)
    //? this代表要执行的函数 因为是函数调用这个方法 拿给obj也就是改变的this来执行
    //? 这里也可以const key = Symbol()来创建唯一key值来执行函数
    obj._fn = this
    const res = obj._fn(...args)
    delete obj._fn
    return res
}

Function.prototype.applyy = function (obj,args) {
    !obj && (obj = globalThis)
    obj._fn = this
    const res = obj._fn(...args)
    delete obj._fn
    return res

}
//? 不管我们给函数 bind 几次，fn 中的 this 永远由第一次 bind 决定
Function.prototype.bindd = function (obj,...args1) {
    !obj && (obj = globalThis)
    return (...args2) => {
        obj._fn = this
        const res = obj._fn(...[...args1, ...args2])
        delete obj._fn;
        return res;
    }
}
let a = {
    b : 1
}
function add(a, b) {
    return a + b
}

console.log(add.calll(a, 1, 2));
console.log(add.applyy(a, [1, 2]));
console.log(add.bindd(a, 1)(2));
//? 应用场景
//? Object.prototype.toString.call 由于toString方法可能被重写(Date、Array、RegExp、Error等)，所以通过call来使数据调用原型上的toString
//? new的过程 会让新对象调用构造函数 会用到call、apply
